const { ethers } = require("hardhat");
const { expect } = require("chai");

describe("项目整体测试", function () {
    let host, helper1, helper2;
    let mockLinkToken;
    let mockVRFCoordinator;
    let randomNumber;
    let message;
    let currencyBrokers;
    let taskEvaluation;
    let helperInformation;
    let task;
    let finishTask;

    let hostbalance;

    let FundsReceivedEvent;
    let taskPublishedEvent;
    let taskFinishedEvent;

    before(async function () {
        [host, helper1, helper2] = await ethers.getSigners();

        // 部署 MockLinkToken
        const MockLinkTokenFactory = await ethers.getContractFactory(
            "MockLinkToken"
        );
        mockLinkToken = await MockLinkTokenFactory.deploy();
        await mockLinkToken.waitForDeployment();
        console.log("MockLinkToken deployed to:", mockLinkToken.target);

        // 部署 MockVRFCoordinator
        const MockVRFCoordinatorFactory = await ethers.getContractFactory(
            "MockVRFCoordinator"
        );
        mockVRFCoordinator = await MockVRFCoordinatorFactory.deploy(
            mockLinkToken.target
        );
        await mockVRFCoordinator.waitForDeployment();
        console.log(
            "MockVRFCoordinator deployed to:",
            mockVRFCoordinator.target
        );

        // 部署 RandomNumber
        const RandomNumberFactory = await ethers.getContractFactory(
            "RandomNumber"
        );
        randomNumber = await RandomNumberFactory.deploy(
            mockVRFCoordinator.target,
            mockLinkToken.target
        );
        await randomNumber.waitForDeployment();
        console.log("RandomNumber deployed to:", randomNumber.target);

        // 部署 Message
        const MessageFactory = await ethers.getContractFactory("Message");
        message = await MessageFactory.deploy();
        await message.waitForDeployment();
        console.log("Message deployed to:", message.target);

        // 部署 CurrencyBrokers
        const CurrencyBrokersFactory = await ethers.getContractFactory(
            "CurrencyBrokers"
        );
        currencyBrokers = await CurrencyBrokersFactory.deploy();
        await currencyBrokers.waitForDeployment();
        console.log("CurrencyBrokers deployed to:", currencyBrokers.target);

        // 部署 TaskEvaluation
        const TaskEvaluationFactory = await ethers.getContractFactory(
            "TaskEvaluation"
        );
        taskEvaluation = await TaskEvaluationFactory.deploy(
            randomNumber.target
        );
        await taskEvaluation.waitForDeployment();
        console.log("TaskEvaluation deployed to:", taskEvaluation.target);

        // 部署 HelperInformation
        const HelperInformationFactory = await ethers.getContractFactory(
            "HelperInformation"
        );
        helperInformation = await HelperInformationFactory.deploy();
        await helperInformation.waitForDeployment();
        console.log("HelperInformation deployed to:", helperInformation.target);

        // 部署 Task
        const TaskFactory = await ethers.getContractFactory("Task");
        task = await TaskFactory.deploy(
            message.target,
            currencyBrokers.target,
            taskEvaluation.target,
            helperInformation.target
        );
        await task.waitForDeployment();
        console.log("Task deployed to:", task.target);
        // 部署 FinishTask
        const FinishTaskFactory = await ethers.getContractFactory("FinishTask");
        finishTask = await FinishTaskFactory.deploy(task.target);
        await finishTask.waitForDeployment();
        console.log("FinishTask deployed to:", finishTask.target);



    });

    beforeEach(async function () {
        FundsReceivedEvent = new Promise((resolve, reject) => {
            const listener = (sender, value) => {
                if (sender === helper1.address) {
                    currencyBrokers.removeListener("FundsReceived", listener);
                    resolve({ sender, value });
                }
            };
            currencyBrokers.on("FundsReceived", listener);
        });
        taskPublishedEvent = new Promise((resolve, reject) => {
            const listener = (taskIndex, acceptor, taskStatus) => {
                if (acceptor == helper1.address) {
                    task.removeListener("TaskPublished", listener);
                    resolve({ taskIndex, acceptor, taskStatus });
                }
            };
            task.on("TaskPublished", listener);
        });
        taskFinishedEvent = new Promise((resolve, reject) => {
            const listener = (taskId, finisher, taskStatus) => {
                if (finisher == helper1.address) {
                    task.removeListener("TaskFinished", listener);
                    resolve({ taskId, finisher, taskStatus });
                }
            };
            task.on("TaskFinished", listener);
        });
    });

    it("", async function () {});
    it("应该正确部署所有合约", async function () {
        expect(mockLinkToken.target).to.exist;
        expect(mockVRFCoordinator.target).to.exist;
        expect(randomNumber.target).to.exist;
        expect(message.target).to.exist;
        expect(currencyBrokers.target).to.exist;
        expect(taskEvaluation.target).to.exist;
        expect(helperInformation.target).to.exist;
        expect(task.target).to.exist;
        expect(finishTask.target).to.exist;
    });
    it("第一步", async function () {
        hostbalance = await currencyBrokers.getOwnBalance();

        const tx = await currencyBrokers
            .connect(helper1)
            .receive({ value: ethers.parseEther("0.1") });
        await tx.wait();
        const newBalance = await currencyBrokers.getOwnBalance();
        let FundsEvent = await FundsReceivedEvent;
        expect(newBalance).to.equal(hostbalance + FundsEvent.value);
        await task.connect(host).publishTask(FundsEvent.sender, 0);
    });
    it("第二步", async function () {
        hostbalance = await currencyBrokers.getOwnBalance();
        const tx = await currencyBrokers
            .connect(helper1)
            .receive({ value: ethers.parseEther("0.1") });
        await tx.wait();
        const newBalance = await currencyBrokers.getOwnBalance();
        let FundsEvent = await FundsReceivedEvent;
        expect(newBalance).to.equal(hostbalance + FundsEvent.value);
        await task.connect(host).publishTask(FundsEvent.sender, 0);

        let taskEvent = await taskPublishedEvent;
        let content = await task
            .connect(helper1)
            .acceptTask(taskEvent.taskIndex);
        // console.log("test content:", content.taskRequirements);
        const returnContent = [123, 456, 789];
        await task.connect(helper1).finishTask(returnContent, taskEvent.taskIndex);
    });
    it("第三步", async function () {
        hostbalance = await currencyBrokers.getOwnBalance();
        const tx = await currencyBrokers
            .connect(helper1)
            .receive({ value: ethers.parseEther("0.1") });
        await tx.wait();
        const newBalance = await currencyBrokers.getOwnBalance();
        let FundsEvent = await FundsReceivedEvent;
        expect(newBalance).to.equal(hostbalance + FundsEvent.value);
        await task.connect(host).publishTask(FundsEvent.sender, 0);

        let taskEvent = await taskPublishedEvent;
        let content = await task
            .connect(helper1)
            .acceptTask(taskEvent.taskIndex);
        // console.log("test content:", content.taskRequirements);
        const returnContent = [123, 456, 789];
        await task.connect(helper1).finishTask(returnContent, taskEvent.taskIndex);
        console.log('a');
        let FinishedEvent = await taskFinishedEvent;
        console.log('a');
        await task.connect(host).evaluateTask(FinishedEvent.taskId);
    });
    it("助手查看账户并提款", async function () {
        let balance = await currencyBrokers.connect(helper1).getOwnBalance();
        await currencyBrokers.connect(helper1).withdrawFunds(balance);
    });
});
